﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ExpressionUtil;
using ExpressionUtil.Exceptions;

namespace ExpressionUtil.UnitTest
{
    /// <summary>
    /// UnitTest1 的摘要说明
    /// </summary>
    [TestClass]
    public class DependencySorterUnitTest
    {
        public DependencySorterUnitTest()
        {
            //
            //TODO: 在此处添加构造函数逻辑
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///获取或设置测试上下文，该上下文提供
        ///有关当前测试运行及其功能的信息。
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region 附加测试属性
        //
        // 编写测试时，还可使用以下附加属性:
        //
        // 在运行类中的第一个测试之前使用 ClassInitialize 运行代码
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // 在类中的所有测试都已运行之后使用 ClassCleanup 运行代码
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // 在运行每个测试之前，使用 TestInitialize 来运行代码
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // 在每个测试运行完之后，使用 TestCleanup 来运行代码
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void TestDependencySorter()
        {
            string[][] test = 
            {
                new string[]{"a","b+c+d+e+f"},
                new string[]{"b","c+d"},
                new string[]{"c","2"},
                new string[]{"d","3"},
                new string[]{"e","4"}
            };
            Dictionary<string, Expression> dic = new Dictionary<string, Expression>();
            for (int i = 0; i < test.Length; i++)
            {
                dic.Add(test[i][0], new Expression(test[i][1]));
            }
            KeyValuePair<string, Expression>[] exps = DependencySorter.Sort(dic);
            Dictionary<string, int> sortedDic = this.ArrayToDic(exps);
            Assert.AreEqual(exps.Length, 5); 
            CollectionAssert.AllItemsAreNotNull(exps);
            Assert.IsTrue(sortedDic["b"] > sortedDic["c"] && sortedDic["b"] > sortedDic["d"]);
            Assert.IsTrue(sortedDic["a"] > sortedDic["b"] && sortedDic["a"] > sortedDic["c"] && 
                sortedDic["a"] > sortedDic["d"] && sortedDic["a"] > sortedDic["e"]);
        }

        [TestMethod]
        public void TestDependencySorterDirecrCross()
        {
            string[][] test = 
            {
                new string[]{"a","b+c"},
                new string[]{"b","d+e"},
                new string[]{"c","d+10"},
                new string[]{"d","f+1"},
                new string[]{"e","4"},
                new string[]{"f","5"},
            };
            Dictionary<string, Expression> dic = new Dictionary<string, Expression>();
            for (int i = 0; i < test.Length; i++)
            {
                dic.Add(test[i][0], new Expression(test[i][1]));
            }
            KeyValuePair<string, Expression>[] exps = DependencySorter.Sort(dic);
            Dictionary<string, int> sortedDic = this.ArrayToDic(exps);
            Assert.AreEqual(exps.Length, 6);
            CollectionAssert.AllItemsAreNotNull(exps);
            Assert.IsTrue(sortedDic["d"] > sortedDic["f"]);
            Assert.IsTrue(sortedDic["c"] > sortedDic["d"]);
            Assert.IsTrue(sortedDic["b"] > sortedDic["d"] && sortedDic["b"] > sortedDic["e"]);
            Assert.IsTrue(sortedDic["a"] > sortedDic["b"] && sortedDic["a"] > sortedDic["c"]);
        }

        [TestMethod]
        public void TestDependencySorterCross()
        {
            string[][] test = 
            {
                new string[]{"a","b+c+d+e+f"},
                new string[]{"b","c+d"},
                new string[]{"c","2"},
                new string[]{"d","3"},
                new string[]{"e","4"},
                new string[]{"f","5"},
                new string[]{"wqwqw","b+c"}
            };
            Dictionary<string, Expression> dic = new Dictionary<string, Expression>();
            for (int i = 0; i < test.Length; i++)
            {
                dic.Add(test[i][0], new Expression(test[i][1]));
            }
            KeyValuePair<string, Expression>[] exps = DependencySorter.Sort(dic);
            Dictionary<string, int> sortedDic = this.ArrayToDic(exps);
            Assert.AreEqual(exps.Length, 7);
            CollectionAssert.AllItemsAreNotNull(exps);
            Assert.IsTrue(sortedDic["b"] > sortedDic["c"] && sortedDic["b"] > sortedDic["d"]);
            Assert.IsTrue(sortedDic["a"] > sortedDic["b"] && sortedDic["a"] > sortedDic["c"] &&
                sortedDic["a"] > sortedDic["d"] && sortedDic["a"] > sortedDic["e"] && sortedDic["a"] > sortedDic["f"]);
            Assert.IsTrue(sortedDic["wqwqw"] > sortedDic["b"] && sortedDic["wqwqw"] > sortedDic["c"]);
        }

        [TestMethod]
        [ExpectedException(typeof(CircularReferenceException),"循环引用测试")]
        public void TestDependencySorterCircularReferenceUndirect()
        {
            string[][] test = 
            {
                new string[]{"a","b+c+d+e+f"},
                new string[]{"b","c+d"},
                new string[]{"c","2"},
                new string[]{"d","a"},
                new string[]{"e","4"},
                new string[]{"f","5"},
            };
            Dictionary<string, Expression> dic = new Dictionary<string, Expression>();
            for (int i = 0; i < test.Length; i++)
            {
                dic.Add(test[i][0], new Expression(test[i][1]));
            }
            KeyValuePair<string, Expression>[] exps = DependencySorter.Sort(dic);
        }

        [TestMethod]
        [ExpectedException(typeof(CircularReferenceException), "循环引用测试")]
        public void TestDependencySorterCircularReferenceDirect()
        {
            string[][] test = 
            {
                new string[]{"a","b+c+d+e+f+a"},
                new string[]{"b","c+d"},
                new string[]{"c","2"},
                new string[]{"d","3"},
                new string[]{"e","4"},
                new string[]{"f","5"},
            };
            Dictionary<string, Expression> dic = new Dictionary<string, Expression>();
            for (int i = 0; i < test.Length; i++)
            {
                dic.Add(test[i][0], new Expression(test[i][1]));
            }
            KeyValuePair<string, Expression>[] exps = DependencySorter.Sort(dic);
        }

        private Dictionary<string, int> ArrayToDic(KeyValuePair<string, Expression>[] exps)
        {
            Dictionary<string, int> ret = new Dictionary<string, int>();
            for (int i = 0; i < exps.Length; i++)
            {
                ret.Add(exps[i].Key, i);
            }
            return ret;
        }
    }
}
